package mornd.value;

import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author: mornd
 * @dateTime: 2023/5/12 - 15:03
 *
 *      手动解析 @Value 注解的 ${} #{}
 */
@ComponentScan
public class Demo {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Demo.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        ConfigurableEnvironment env = context.getEnvironment();

        ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();
        resolver.setBeanFactory(beanFactory);

        // 获取 @Value 注解的内容
        DependencyDescriptor dd =
                // required：true，如果没有则抛出异常
                new DependencyDescriptor(Bean1.class.getDeclaredField("home"), false);
        // 获取 value 注解的值，此时还没解析 ${Java_Home}
        String home = resolver.getSuggestedValue(dd).toString();
        home = env.resolvePlaceholders(home);
        System.out.println("home=====>" + home);

        DependencyDescriptor dd2 =
                new DependencyDescriptor(Bean1.class.getDeclaredField("age"), false);
        String age = resolver.getSuggestedValue(dd2).toString();
        age = env.resolvePlaceholders(age);
        // 使用 beanFactory 做类型转换
        Integer intAge = (Integer) beanFactory.getTypeConverter().convertIfNecessary(age, dd2.getDependencyType());
        System.out.println("age=====>" + intAge);


        // 解析 #{}
        DependencyDescriptor dd3 =
                new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"), false);
        String bean2 = resolver.getSuggestedValue(dd3).toString();
        bean2 = env.resolvePlaceholders(bean2);
        // 开始解析 #{}
        Object bean2Result = beanFactory.getBeanExpressionResolver().evaluate(bean2, new BeanExpressionContext(beanFactory, null));
        bean2Result = beanFactory.getTypeConverter().convertIfNecessary(bean2Result, dd3.getDependencyType());
        System.out.println("bean2=====>" + bean2Result);
    }

    @ToString
    @Component
    static class Bean1 {
        @Value("${Java_Home}")
        private String home;
        @Value("20")
        private int age;

        @Value("#{@bean2}")
        private Bean2 bean2;
    }

    @Component("bean2")
    static class Bean2 {}
}
